package vision;

import geometrie.Transformation;
import scene.Facette3D;
import scene.Scene;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class AfficheurScene implements Affichable {
	private static final double INITIAL_ANGLE = Math.PI / 6;
	private Camera cam;
	private Scene originalScene; // original scene(Ref_Scene)
	private List<Facette3D> camScene; // scene projected to the Ref_Cam
	private List<Facette3D> projectedScene; // projected scene(2D)
	private int dimU;
	private int dimV;
	private double pixelSize;
	private List<ImageFacette> discreteScene; // discretized scene (to be used
												// for displaying proposes)

	/**
	 * Constructor of a new AfficheurScene
	 * 
	 * @param scene
	 *            the scene
	 * @param dimU
	 *            the horizontal dimension
	 * @param dimV
	 *            the vertical dimension
	 * @param taillePixel
	 *            the size of the pixel
	 */
	public AfficheurScene(Scene scene, int dimU, int dimV, double taillePixel) {
		this.originalScene = scene;
		this.camScene = null;
		this.projectedScene = null;
		this.dimU = dimU;
		this.dimV = dimV;
		this.pixelSize = taillePixel;
		this.cam = new Camera((Math.min(dimU, dimV))
				/ (2 * Math.tan(INITIAL_ANGLE)));
		this.discreteScene = new ArrayList<ImageFacette>();
	}

	@Override
	public Iterator<ImageFacette> getImagesFacettes() {
		return discreteScene.iterator();
	}

	@Override
	public void positionneCamera(Transformation t) {
		cam.setRefCamera(t);
		camScene = cam.changeReferential(originalScene);
		camScene = Scene.altitude(camScene);
		projectedScene = cam.project(camScene);
		discretizeScene();
	}

	@Override
	public void setToCameraOrthographique() {
		cam.setToParallel();
		//camScene = cam.changeReferential(originalScene);
		camScene = Scene.altitude(camScene);
		projectedScene = cam.project(camScene);
		discretizeScene();
	}

	@Override
	public void setToCameraPerspective(int angle) {
		double radAngle = (Math.PI / 180) * angle;
		cam.setToPerspective((Math.min(dimU, dimV)) / (2 * Math.tan(radAngle)));
		//camScene = cam.changeReferential(originalScene);
		camScene = Scene.altitude(camScene);
		projectedScene = cam.project(camScene);
		discretizeScene();
	}

	/**
	 * Sort the ImageFacette in the corrector order for displaying proposes
	 * 
	 */
	private void sortFacettes() {
		Collections.sort(discreteScene); // sort in ascending order
		Collections.reverse(discreteScene); // reverse to get descending order
	}

	/**
	 * Discretize the scene. Create the scene to be used for displaying proposes
	 * which gives the coordinates X and Y of the pixels in the screen.
	 */
	public void discretizeScene() {
		Iterator<Facette3D> facetteIterator = projectedScene.iterator();
		ImageFacette newImage;
		discreteScene.clear();
		while (facetteIterator.hasNext()) {
			newImage = new ImageFacette(facetteIterator.next(), pixelSize);
			discreteScene.add(newImage);
		}
		sortFacettes();
	}
}
